/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frxml_parse.c                                      */
/*  NOTE      =  解析XML配置文件                                   */
/*  DATE      = 2015/03/20     by geyh                             */
/*******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libxml/xpath.h>
#include <libxml/parser.h>
#include <unistd.h>

#include "frlist.h"
#include "frmem.h"
#include "frsutl.h"
#include "frcomm.h"
#include "frlog.h"
#include "frxml_parse.h"

/*
 * \判断 xml协议
 *
 * \p_data_in
 * \i_data_len
 *
 * \return              FR_SUCC:    成功
 *                      FR_FAIL:    失败
 */
int frxml_isxml(char *p_data_in, int i_data_len)
{
    if (p_data_in == NULL || i_data_len < 5)
        return FR_FAIL;

    //"<?xml "
    if (memcmp(p_data_in, "<?xml " ,6) != 0)
        return FR_FAIL;

    i_data_len -= 6;
    p_data_in += 6;

    //跳过空格
    while (*p_data_in == ' ' && i_data_len)
    {
        p_data_in++;
        i_data_len--;
    }
    if (i_data_len < 7)
        return FR_FAIL;

    //version
    if (memcmp(p_data_in, "version", 7) != 0)
        return FR_FAIL;

    i_data_len -= 7;
    p_data_in += 7;

    //跳过空格
    while (*p_data_in == ' ' && i_data_len)
    {
        p_data_in++;
        i_data_len--;
    }

    //等号
    if (*p_data_in != '=')
        return FR_FAIL;

    p_data_in++;
    i_data_len--;

    //跳过空格
    while (*p_data_in == ' ' && i_data_len)
    {
        p_data_in++;
        i_data_len--;
    }

    //版本号
    if (memcmp(p_data_in,"\"1.",3) != 0 && memcmp(p_data_in,"'1.",3) != 0)
        return FR_FAIL;

    p_data_in += 3;
    i_data_len -= 3;

    if (i_data_len < 2)
        return FR_FAIL;

    if (*p_data_in < '0' || *p_data_in > '9' || (*(p_data_in + 1) != '"' && *(p_data_in + 1) != '\''))
        return FR_FAIL;

    //?>结束
    p_data_in = (char *) memchr(p_data_in, '?', i_data_len);
    if (p_data_in == NULL || *(p_data_in + 1) != '>')
        return FR_FAIL;

    return FR_SUCC;
}

/*
 * \获取 encoding
 *
 * \p_data_in
 * \i_data_len
 *
 * \pp_encoding
 *
 * \return              FR_SUCC:    成功
 *                      FR_FAIL:    失败
 */
int frxml_get_encoding(char *p_data_in, int i_data_len, char **pp_encoding)
{
    char arr_encoding[32];
    char *p_pos = NULL;
    char *p_pos_tmp = NULL;

    if (p_data_in == NULL || i_data_len < 5 || pp_encoding == NULL)
        return FR_FAIL;

    p_pos = p_data_in;

    //"<?xml "
    if (memcmp(p_data_in,"<?xml " ,6) != 0)
        return FR_FAIL;

    i_data_len -= 6;
    p_data_in += 6;

    //跳过空格
    while (*p_data_in == ' ' && i_data_len)
    {
        p_data_in++;
        i_data_len--;
    }
    if (i_data_len < 7)
        return FR_FAIL;

    //version
    if (memcmp(p_data_in,"version",7) != 0)
        return FR_FAIL;

    i_data_len -= 7;
    p_data_in += 7;

    //跳过空格
    while (*p_data_in == ' ' && i_data_len)
    {
        p_data_in++;
        i_data_len--;
    }

    //等号
    if (*p_data_in != '=')
        return FR_FAIL;

    p_data_in++;
    i_data_len--;

    //跳过空格
    while (*p_data_in == ' ' && i_data_len)
    {
        p_data_in++;
        i_data_len--;
    }

    //版本号
    if (memcmp(p_data_in,"\"1.",3) != 0 && memcmp(p_data_in,"'1.",3) != 0)
        return FR_FAIL;

    p_data_in += 3;
    i_data_len -= 3;

    if (i_data_len < 2)
        return FR_FAIL;

    if (*p_data_in < '0' || *p_data_in > '9' || (*(p_data_in + 1) != '"' && *(p_data_in + 1) != '\''))
        return FR_FAIL;

    //?>结束
    p_data_in = (char *) memchr(p_data_in, '?', i_data_len);
    if (p_data_in == NULL || *(p_data_in + 1) != '>')
        return FR_FAIL;

    //获取encoding
    p_pos = strstr(p_pos, "encoding");
    if (p_pos == NULL || p_pos > p_data_in)
    {
        *pp_encoding = frstrdup("utf-8");
        return FR_SUCC;
    }

    p_pos_tmp = strchr(p_pos, '"');
    if (p_pos_tmp == NULL || p_pos_tmp > p_data_in)
    {
        p_pos_tmp = strchr(p_pos, '\'');
        if (p_pos_tmp == NULL || p_pos_tmp > p_data_in)
        {
            *pp_encoding = frstrdup("utf-8");
            return FR_SUCC;
        }
    }
    p_pos = p_pos_tmp;

    p_pos++;
    snprintf(arr_encoding, sizeof(arr_encoding), "%s", p_pos);
    p_pos = strchr(arr_encoding, '"');
    if (p_pos == NULL)
    {
        p_pos = strchr(arr_encoding, '\'');
        if (p_pos == NULL)
        {
            *pp_encoding = frstrdup("utf-8");
            return FR_SUCC;
        }
    }

    *p_pos = '\0';
    *pp_encoding = frstrdup(arr_encoding);
    return FR_SUCC;
}



/*******************************************************************************
*  FUNC     :  链表打印节点
*  ARGS     :  
*           :
*  NOTE     :
*******************************************************************************/
FR_STATIC int __list_node_print(Frlist_node *p_st_node, const void *p_data)
{
    Frvar_field *p_var_field = NULL;

    if(p_st_node && p_st_node->data)
    {
        p_var_field = (Frvar_field *) p_st_node->data;
        printf("%s\n",p_var_field->field_value.p_value);
        return 1;
    }

    return 0;
}


void frxml_dbg_list(Frlist_header *p_list_header)
{
    if(p_list_header == NULL)
        return;

    frlist_run(p_list_header, NULL, __list_node_print);
    return;
}

/*******************************************************************************
*  FUNC     :  释放链表节点
*  ARGS     :  
*           :
*  NOTE     :
*******************************************************************************/
FR_STATIC void __xml_node_free(Frlist_node *p_st_node)
{
    Frvar_field *p_var_field = NULL;

    if(p_st_node && p_st_node->data)
    {
        p_var_field = (Frvar_field *) p_st_node->data;
        if(p_var_field->p_field_name)
            frfree(p_var_field->p_field_name);
        if(p_var_field->field_value.p_value)
            frfree(p_var_field->field_value.p_value);
        frfree(p_var_field);
    }

    return;

}


void frxml_free_list(Frlist_header **pp_list_header)
{
    Frlist_header *p_st_header = NULL;

    if(pp_list_header == NULL)
        return;

    p_st_header = *pp_list_header;
    frlist_destroy(p_st_header, __xml_node_free);
    *pp_list_header = NULL;
    return;
}



xmlDocPtr frxml_open_file(const char *p_file_name)
{
    xmlDocPtr p_st_doc = NULL;
    if(p_file_name == NULL)
        return NULL;

    //判断文件是否存在
    if(access(p_file_name,0) != 0)
        return NULL;

    p_st_doc = xmlReadFile(p_file_name, NULL, XML_PARSE_NOERROR|XML_PARSE_NOWARNING);
    if(p_st_doc == NULL)
    {
        FRLOG_ERROR_DETAIL("XML file parse err");
        return NULL;
    }

    return p_st_doc;

}


void frxml_save_file(xmlDocPtr p_st_doc, const char *p_file_name)
{
    if(p_st_doc == NULL || p_file_name == NULL)
        return;

    xmlSaveFormatFile(p_file_name, p_st_doc, 0);
    return;
}


void frxml_close_file(xmlDocPtr p_st_doc)
{
    if(p_st_doc == NULL)
        return;

    xmlFreeDoc(p_st_doc);
    return;
}

/*******************************************************************************
*  FUNC     :  取某个节点集
*  ARGS     :  xmlDocPtr  p_st_doc   （文件节点）
*           :  xmlChar *p_xpath   （节点路径）取第三级节点时(/root/node1/node2)
*  NOTE     :
*******************************************************************************/
FR_STATIC xmlXPathObjectPtr __get_nodeset(xmlDocPtr p_st_doc, const xmlChar *p_xpath)
{
    xmlXPathContextPtr p_st_context;
    xmlXPathObjectPtr p_st_result;
    p_st_context = xmlXPathNewContext(p_st_doc);
    if (p_st_context == NULL)
    {
        //printf("p_st_context is NULL\n");
        return NULL;
    }
    p_st_result = xmlXPathEvalExpression(p_xpath, p_st_context);
    xmlXPathFreeContext(p_st_context);
    if (p_st_result == NULL)
    {
        //printf("xmlXPathEvalExpression return NULL\n");
        return NULL;
    }
    if (xmlXPathNodeSetIsEmpty(p_st_result->nodesetval))
    {
        xmlXPathFreeObject(p_st_result);
        //printf("nodeset is empty\n");
        return NULL;
    }
    return p_st_result;
}

/*******************************************************************************
*  FUNC     :  获取属性值
*  ARGS     :  p_keyword
*           :  p_value

*  NOTE     :
*******************************************************************************/
FR_STATIC int __xmlnode_get_prop(xmlNodePtr p_st_cur, const char *p_prop_name, char **pp_value)
{
    xmlChar *p_prop_value = NULL;
    char *p_value = NULL;

    p_prop_value = xmlGetProp(p_st_cur,(const xmlChar *)p_prop_name);
    if(p_prop_value == NULL)
        return FR_FAIL;

    p_value = frstrdup((char *)p_prop_value);
    if(p_value == NULL)
    {
        xmlFree(p_prop_value);
        return FR_FAIL;
    }
    frtrim(p_value);

    xmlFree(p_prop_value);
    *pp_value = p_value;
    return FR_SUCC;

}
/*******************************************************************************
*  FUNC     :  从指针中获取字符串
*  ARGS     :  p_st_doc
*           :  p_xpath （节点路径）取第三级节点时(/root/node1/node2)
*           :  p_value

*  NOTE     :
*******************************************************************************/
FR_STATIC int __create_new_xpath(xmlDocPtr p_st_doc, const char *p_xpath, const char *p_keyword, const char *p_value)
{
    char *p_pos = NULL;
    char *p_pos_tmp = NULL;
    char *p_xpath_tmp = NULL;
    char arr_key[1024];
    xmlXPathObjectPtr p_result = NULL;
    xmlXPathObjectPtr p_result_tmp = NULL;
    xmlNodeSetPtr nodeset = NULL;
    xmlNodePtr p_st_cur = NULL;

    if(p_xpath == NULL || p_keyword == NULL || p_value == NULL || *p_keyword == '\0')
        return FR_FAIL;

    //dup
    p_xpath_tmp = frstrdup(p_xpath);

    //取根节点
    p_pos = strchr(p_xpath_tmp + 1, '/');
    if(p_pos)
        *p_pos = '\0';
    //第一级节点必须存在
    p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath_tmp);
    if(p_result == NULL)
        goto ERROR;

    //复原并且指针后移
    if(p_pos)
    {
        *p_pos = '/';
        p_pos++;
        p_pos_tmp = p_pos;
    }

    p_result_tmp = p_result;

    while(p_pos)
    {
        p_pos = strchr(p_pos, '/');
        if(p_pos)
            *p_pos = '\0';
        //获取字段名
        snprintf(arr_key,sizeof(arr_key),"%s",p_pos_tmp);

        //第一级节点必须存在
        p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath_tmp);
        if(p_result == NULL)
        {
            nodeset = p_result_tmp->nodesetval;
            p_st_cur = nodeset->nodeTab[0];
            //添加节点
            xmlNewTextChild(p_st_cur, NULL, (const xmlChar *)arr_key, (const xmlChar *)NULL);

            xmlXPathFreeObject (p_result_tmp);
            //读取刚建立的节点
            p_result_tmp = __get_nodeset(p_st_doc,(xmlChar *)p_xpath_tmp);
            if(p_result_tmp == NULL)
                goto ERROR;
        }
        else
        {
            xmlXPathFreeObject (p_result_tmp);
            p_result_tmp = p_result;
        }
        if(p_pos)
        {
            *p_pos = '/';
            p_pos++;
            p_pos_tmp = p_pos;
        }
    }

    nodeset = p_result_tmp->nodesetval;
    p_st_cur = nodeset->nodeTab[0];
    xmlNewTextChild(p_st_cur, NULL, (const xmlChar *)p_keyword, (const xmlChar *)p_value);
    xmlXPathFreeObject (p_result_tmp);

    frfree(p_xpath_tmp);
    return FR_SUCC;


ERROR:
    if(p_xpath_tmp)
        frfree(p_xpath_tmp);
    if(p_result)
        xmlXPathFreeObject (p_result);

    return FR_FAIL;
}


int frxml_get2ptr_prop_string(xmlDocPtr p_st_doc, const char *p_xpath, const char *p_keyword, const char *p_prop_name, char **pp_value)
{
    xmlXPathObjectPtr p_result = NULL;
    int i_loop = 0;
    xmlNodePtr p_st_cur = NULL;
    xmlNodeSetPtr nodeset = NULL;
    int i_ret = 0;

    if(p_st_doc == NULL || pp_value == NULL || p_keyword == NULL || *p_keyword == '\0')
        return FR_FAIL;

    if(p_xpath == NULL || *p_xpath == '\0' || (*p_xpath == '/' && p_xpath[1] == '\0'))
    {
        //取根节点
        p_st_cur = xmlDocGetRootElement(p_st_doc);
        if (!xmlStrcmp(p_st_cur->name, (const xmlChar *)p_keyword))
        {
            i_ret = __xmlnode_get_prop(p_st_cur, p_prop_name, pp_value);
            xmlXPathFreeObject (p_result);
            return i_ret;
        }
        return FR_FAIL;
    }

    //获取节点集
    p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath);
    if(p_result)
    {
        nodeset = p_result->nodesetval;
        for (i_loop=0; i_loop < nodeset->nodeNr; i_loop++)
        {
            p_st_cur = nodeset->nodeTab[i_loop];
            p_st_cur = p_st_cur->xmlChildrenNode;
            while(p_st_cur!=NULL)
            {
                //比较字段名
                if (!xmlStrcmp(p_st_cur->name, (const xmlChar *)p_keyword))
                {
                    i_ret = __xmlnode_get_prop(p_st_cur, p_prop_name, pp_value);
                    xmlXPathFreeObject (p_result);
                    return i_ret;
                }
                p_st_cur = p_st_cur->next;
            }
        }
        //如果不存在
    }

    if(p_result)
        xmlXPathFreeObject (p_result);

    return FR_FAIL;
}

int frxml_get2doc_prop_string(const char *p_file_name, const char *p_xpath, const char *p_keyword, const char *p_prop_name, char **pp_value)
{
    xmlDocPtr p_st_doc = NULL;
    int i_ret = 0;

    if (p_file_name == NULL ||  p_keyword == NULL || p_prop_name == NULL || pp_value == NULL)
        return FR_FAIL;

    p_st_doc = xmlReadFile(p_file_name, NULL, XML_PARSE_NOERROR|XML_PARSE_NOWARNING);
    if(p_st_doc == NULL)
    {
        FRLOG_ERROR_DETAIL("XML file parse err");
        return FR_FAIL;
    }
    i_ret = frxml_get2ptr_prop_string(p_st_doc, p_xpath, p_keyword, p_prop_name, pp_value);

    xmlFreeDoc(p_st_doc);
    return i_ret;

}



int frxml_get2ptr_string(xmlDocPtr p_st_doc, const char *p_xpath, const char *p_keyword, char **pp_value)
{
    xmlXPathObjectPtr p_result = NULL;
    int i_loop = 0;
    xmlChar *p_content = NULL;
    xmlNodePtr p_st_cur = NULL;
    xmlNodeSetPtr nodeset = NULL;
    char *p_value = NULL;

    if(p_st_doc == NULL || p_xpath == NULL || p_keyword == NULL
        || pp_value == NULL || *p_xpath == '\0' || *p_keyword == '\0')
        return FR_FAIL;

    //获取节点集
    p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath);
    if(p_result)
    {
        nodeset = p_result->nodesetval;
        for (i_loop=0; i_loop < nodeset->nodeNr; i_loop++)
        {
            p_st_cur = nodeset->nodeTab[i_loop];
            p_st_cur = p_st_cur->xmlChildrenNode;
            while(p_st_cur!=NULL)
            {
                //比较字段名
                if (!xmlStrcmp(p_st_cur->name, (const xmlChar *)p_keyword))
                {
                    p_content = xmlNodeGetContent(p_st_cur);
                    p_value = frstrdup((char *)p_content);
                    xmlFree(p_content);
                    if(p_value == NULL)
                    {
                        xmlXPathFreeObject (p_result);
                        return FR_FAIL;
                    }

                    //设置出力参数
                    frtrim(p_value);
                    *pp_value = p_value;
                    xmlXPathFreeObject (p_result);
                    return FR_SUCC;
                }
                p_st_cur = p_st_cur->next;
            }
        }
        //如果不存在
    }

    if(p_result)
        xmlXPathFreeObject (p_result);

    return FR_FAIL;

}


int frxml_get2ptr_int(xmlDocPtr p_st_doc, const char *p_xpath, const char *p_keyword, int *p_i_value)
{
    char *p_value = NULL;
    int i_ret = 0;

    if(p_st_doc == NULL || p_xpath == NULL || p_keyword == NULL || p_i_value == NULL)
        return FR_FAIL;

    i_ret = frxml_get2ptr_string(p_st_doc, p_xpath, p_keyword, &p_value);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_value != NULL)
    {
        *p_i_value = atoi(p_value);
        frfree(p_value);
        return FR_SUCC;
    }

    return FR_FAIL;

}


int frxml_get2ptr_float(xmlDocPtr p_st_doc, const char *p_xpath, const char *p_keyword, float *p_f_value)
{
    char *p_value = NULL;
    int i_ret = 0;

    if(p_st_doc == NULL || p_xpath == NULL || p_keyword == NULL || p_f_value == NULL)
        return FR_FAIL;

    i_ret = frxml_get2ptr_string(p_st_doc, p_xpath, p_keyword, &p_value);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    if(p_value != NULL)
    {
        *p_f_value = atof(p_value);
        frfree(p_value);
        return FR_SUCC;
    }

    return FR_FAIL;
}


int frxml_get2doc_string(const char *p_file_name, const char *p_xpath, const char *p_keyword, char **pp_value)
{
    xmlDocPtr p_st_doc = NULL;
    int i_ret = 0;

    if (p_xpath == NULL || p_keyword == NULL || pp_value == NULL)
        return FR_FAIL;

    p_st_doc = xmlReadFile(p_file_name, NULL, XML_PARSE_NOERROR|XML_PARSE_NOWARNING);
    if(p_st_doc == NULL)
    {
        FRLOG_ERROR_DETAIL("XML file parse err");
        return FR_FAIL;
    }
    i_ret = frxml_get2ptr_string(p_st_doc, p_xpath, p_keyword, pp_value);

    //如果存在  修改内容
    xmlFreeDoc(p_st_doc);
    return i_ret;

}


int frxml_get2doc_int(const char *p_file_name, const char *p_xpath, const char *p_keyword, int *p_i_value)
{
    char *p_value = NULL;
    int i_ret = 0;

    if(p_file_name == NULL || p_xpath == NULL || p_keyword == NULL || p_i_value == NULL)
        return FR_FAIL;
        
    i_ret = frxml_get2doc_string(p_file_name, p_xpath, p_keyword, &p_value);
    if(i_ret == FR_FAIL)
        return i_ret;

    if(p_value != NULL)
    {
        *p_i_value = atoi(p_value);
        frfree(p_value);
        return FR_SUCC;
    }
    return FR_FAIL;

}


int frxml_get2doc_float(const char *p_file_name, const char *p_xpath, const char *p_keyword, float *p_f_value)
{
    char *p_value = NULL;
    int i_ret = 0;

    if(p_file_name == NULL || p_xpath == NULL || p_keyword == NULL || p_f_value == NULL)
        return FR_FAIL;

    i_ret = frxml_get2doc_string(p_file_name, p_xpath, p_keyword, &p_value);
    if(i_ret == FR_FAIL)
        return i_ret;

    if(p_value)
    {
        *p_f_value = atof(p_value);
        frfree(p_value);
        return FR_SUCC;
    }

    return FR_FAIL;

}


int frxml_insert2ptr_content(xmlDocPtr p_st_doc,const char *p_xpath, const char *p_keyword, const char *p_value)
{
    xmlXPathObjectPtr p_result = NULL;
    xmlNodePtr p_st_cur = NULL;
    xmlNodeSetPtr nodeset = NULL;
    int i_ret = 0;

    if(p_st_doc == NULL || p_xpath == NULL || p_keyword == NULL)
        return FR_FAIL;

    //获取节点集
    p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath);
    if(p_result)
    {
        nodeset = p_result->nodesetval;
        p_st_cur = nodeset->nodeTab[0];
        xmlNewTextChild(p_st_cur, NULL, (const xmlChar *)p_keyword, (const xmlChar *)p_value);

        xmlXPathFreeObject (p_result);
        return FR_SUCC;
    }

    i_ret = __create_new_xpath(p_st_doc, p_xpath, p_keyword, p_value);

    if(p_result)
        xmlXPathFreeObject (p_result);
    return i_ret;

}

int frxml_insert2doc_content(const char *p_file_name,const char *p_xpath, const char *p_keyword, const char *p_value)
{
    xmlDocPtr p_st_doc = NULL;
    int i_ret = 0;

    if(p_file_name == NULL || p_xpath == NULL || p_keyword == NULL)
        return FR_FAIL;

    p_st_doc = xmlReadFile(p_file_name, NULL, XML_PARSE_NOERROR|XML_PARSE_NOWARNING);
    if(p_st_doc == NULL)
    {
        FRLOG_ERROR_DETAIL("XML file parse err");
        return FR_FAIL;
    }

    i_ret = frxml_insert2ptr_content(p_st_doc, p_xpath, p_keyword, p_value);

    if(i_ret == FR_SUCC)
        frxml_save_file(p_st_doc, p_file_name);

    xmlFreeDoc(p_st_doc);
    return i_ret;

}


int frxml_update2doc_content(const char *p_file_name, const char *p_xpath, const char *p_keyword, const char *p_value)
{
    xmlDocPtr p_st_doc = NULL;
    xmlXPathObjectPtr p_result = NULL;
    int i_loop = 0;
    xmlChar *p_content = NULL;
    xmlNodePtr p_st_cur = NULL;
    xmlNodeSetPtr nodeset = NULL;

    if(p_value == NULL || p_file_name == NULL || p_xpath == NULL || p_keyword == NULL)
        return FR_FAIL;

    p_st_doc = xmlReadFile(p_file_name, NULL, XML_PARSE_NOERROR|XML_PARSE_NOWARNING);
    if(p_st_doc == NULL)
    {
        FRLOG_ERROR_DETAIL("XML file parse err");
        return FR_FAIL;
    }

    //获取节点集
    p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath);
    if(p_result)
    {
        nodeset = p_result->nodesetval;
        for (i_loop=0; i_loop < nodeset->nodeNr; i_loop++)
        {
            p_st_cur = nodeset->nodeTab[i_loop];
            p_st_cur = p_st_cur->xmlChildrenNode;
            while(p_st_cur!=NULL)
            {
                if (!xmlStrcmp(p_st_cur->name, (const xmlChar *)p_keyword))
                {
                    p_content = xmlNodeGetContent(p_st_cur);
                    xmlFree(p_content);
                    xmlNodeSetContent(p_st_cur, (const xmlChar *)p_value);

                    xmlSaveFormatFile(p_file_name, p_st_doc, 0);
                    xmlXPathFreeObject (p_result);
                    xmlFreeDoc(p_st_doc);
                    return FR_SUCC;
                }
                p_st_cur = p_st_cur->next;
            }
        }
        //如果不存在
    }

    if(p_result)
        xmlXPathFreeObject (p_result);

    xmlFreeDoc(p_st_doc);
    return FR_FAIL;

}


int frxml_del2doc_all_cont(const char *p_file_name, const char *p_xpath, const char *p_keyword)
{
    xmlDocPtr p_st_doc = NULL;
    xmlXPathObjectPtr p_result = NULL;
    int i_loop = 0;
    xmlNodePtr p_st_cur = NULL;
    xmlNodePtr node_tmp = NULL;
    xmlNodeSetPtr nodeset = NULL;

    if(p_file_name == NULL || p_xpath == NULL || p_keyword == NULL)
        return FR_FAIL;

    p_st_doc = xmlReadFile(p_file_name, NULL, XML_PARSE_NOERROR|XML_PARSE_NOWARNING);
    if(p_st_doc == NULL)
    {
        FRLOG_ERROR_DETAIL("XML file parse err");
        return FR_FAIL;
    }

    //获取节点集
    p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath);
    if(p_result)
    {
        nodeset = p_result->nodesetval;
        for (i_loop=0; i_loop < nodeset->nodeNr; i_loop++)
        {
            p_st_cur = nodeset->nodeTab[i_loop];
            p_st_cur = p_st_cur->xmlChildrenNode;
            while(p_st_cur!=NULL)
            {
                if (!xmlStrcmp(p_st_cur->name, (const xmlChar *)p_keyword))
                {
                    node_tmp = p_st_cur;
                    p_st_cur = p_st_cur->next;
                    xmlUnlinkNode(node_tmp);
                    xmlFreeNodeList(node_tmp);
                    continue;
                }
                p_st_cur = p_st_cur->next;
            }
        }

        xmlSaveFormatFile(p_file_name, p_st_doc, 0);
    }

    if(p_result)
        xmlXPathFreeObject (p_result);

    xmlFreeDoc(p_st_doc);
    return FR_SUCC;

}


int frxml_del2doc_one_cont(const char *p_file_name, const char *p_xpath, const char *p_keyword, const char *p_value)
{
    xmlDocPtr p_st_doc = NULL;
    xmlXPathObjectPtr p_result = NULL;
    int i_loop = 0;
    xmlNodePtr p_st_cur = NULL;
    xmlNodePtr node_tmp = NULL;
    xmlNodeSetPtr nodeset = NULL;
    xmlChar *p_content = NULL;

    if(p_file_name == NULL || p_xpath == NULL || p_keyword == NULL)
        return FR_FAIL;

    p_st_doc = xmlReadFile(p_file_name, NULL, XML_PARSE_NOERROR|XML_PARSE_NOWARNING);
    if(p_st_doc == NULL)
    {
        FRLOG_ERROR_DETAIL("XML file parse err");
        return FR_FAIL;
    }

    //获取节点集
    p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath);
    if(p_result)
    {
        nodeset = p_result->nodesetval;
        for (i_loop=0; i_loop < nodeset->nodeNr; i_loop++)
        {
            p_st_cur = nodeset->nodeTab[i_loop];
            p_st_cur = p_st_cur->xmlChildrenNode;
            while(p_st_cur!=NULL)
            {
                if (!xmlStrcmp(p_st_cur->name, (const xmlChar *)p_keyword))
                {
                    p_content = xmlNodeGetContent(p_st_cur);
                    if(p_content == NULL)
                    {
                        if(p_result)
                            xmlXPathFreeObject (p_result);
                        xmlFreeDoc(p_st_doc);
                        return FR_FAIL;
                    }
                    if(!xmlStrcmp(p_content, (const xmlChar *)p_value))
                    {
                        node_tmp = p_st_cur->next;
                        xmlUnlinkNode(p_st_cur);
                        xmlFreeNodeList(p_st_cur);
                        p_st_cur = node_tmp;

                        xmlFree(p_content);
                        xmlXPathFreeObject (p_result);
                        xmlSaveFormatFile(p_file_name, p_st_doc, 0);
                        xmlFreeDoc(p_st_doc);
                        return FR_SUCC;
                    }
                    xmlFree(p_content);
                    p_content = NULL;
                }
                p_st_cur = p_st_cur->next;
            }
        }
    }

    if(p_result)
        xmlXPathFreeObject (p_result);

    xmlSaveFormatFile(p_file_name, p_st_doc, 0);
    xmlFreeDoc(p_st_doc);
    return FR_SUCC;

}

int frxml_get_string_list(const char *p_file_name,const char *p_xpath, const char *p_keyword, Frlist_header **pp_list_header)
{
    xmlDocPtr p_st_doc = NULL;
    xmlXPathObjectPtr p_result = NULL;
    int i_loop = 0;
    xmlChar *p_value = NULL;
    xmlNodePtr p_st_cur = NULL;
    Frlist_node *p_st_node = NULL;
    char *p_node_data = NULL;
    xmlNodeSetPtr nodeset = NULL;
    Frvar_field *p_var_field = NULL;
    Frlist_header *p_list_header = NULL;

    if(pp_list_header == NULL || p_file_name == NULL || p_xpath == NULL)
        return FR_FAIL;

    p_st_doc = xmlReadFile(p_file_name, NULL, XML_PARSE_NOERROR|XML_PARSE_NOWARNING);
    if(p_st_doc == NULL)
    {
        FRLOG_ERROR_DETAIL("XML file parse err");
        return FR_FAIL;
    }

    //获取节点集
    p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath);
    if(p_result)
    {
        nodeset = p_result->nodesetval;
        p_list_header = frlist_create();
        if(p_list_header == NULL)
        {
            xmlFreeDoc(p_st_doc);
            return FR_FAIL;
        }
        for (i_loop=0; i_loop < nodeset->nodeNr; i_loop++)
        {
            p_st_cur = nodeset->nodeTab[i_loop];
            p_st_cur = p_st_cur->xmlChildrenNode;
            while(p_st_cur!=NULL)
            {
                if(p_st_cur->type != XML_ELEMENT_NODE)
                {
                    p_st_cur = p_st_cur->next;
                    continue;
                }
                if (!xmlStrcmp(p_st_cur->name, (const xmlChar *)p_keyword))
                {
                    p_value = xmlNodeGetContent(p_st_cur);
                    if (p_value != NULL)
                    {
                        p_var_field = (Frvar_field *) frmalloc(sizeof(Frvar_field));
                        if(p_var_field == NULL)
                            goto ERROR;

                        p_var_field->em_data_type = FRSTRING;
                        p_var_field->p_field_name = NULL;
                        p_var_field->field_value.p_value = frstrdup((const char *)p_value);
                        xmlFree(p_value);
                        if(p_var_field->field_value.p_value == NULL)
                            goto ERROR;

                        frtrim(p_var_field->field_value.p_value);
                        p_st_node = frlist_node_create(p_var_field);
                        if(p_st_node == NULL)
                            goto ERROR;

                        frlist_add_tail(p_list_header,p_st_node);
                    }
                }
                p_st_cur = p_st_cur->next;
            }
        }
        *pp_list_header = p_list_header;
        xmlXPathFreeObject (p_result);
        xmlFreeDoc(p_st_doc);
        return FR_SUCC;
    }

ERROR:
    if(p_node_data)
        frfree(p_node_data);
    if(p_value)
        xmlFree(p_value);
    if(p_result)
        xmlXPathFreeObject (p_result);

    if(p_list_header)
        frxml_free_list(&p_list_header);

    if(p_var_field)
    {
        if(p_var_field->field_value.p_value)
            frfree(p_var_field->field_value.p_value);
        frfree(p_var_field);
    }

    xmlFreeDoc(p_st_doc);
    return FR_FAIL;

}


int frxml_get_int_list(const char *p_file_name,const char *p_xpath, const char *p_keyword, Frlist_header **pp_list_header)
{
    int i_ret = 0;
    int i_loop = 0;
    int i_lst_size = 0;
    Frlist_node *p_st_node = NULL;
    Frvar_field *p_var_field = NULL;
    char *p_pos_tmp = NULL;

    if(p_file_name == NULL || p_xpath == NULL || p_keyword == NULL|| pp_list_header == NULL)
        return FR_FAIL;

    i_ret = frxml_get_string_list(p_file_name, p_xpath, p_keyword, pp_list_header);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_lst_size = frlist_size(*pp_list_header);
    for(i_loop = 0;i_loop < i_lst_size; i_loop++)
    {
        p_st_node = frlist_node_idx(*pp_list_header, i_loop);
        p_var_field = (Frvar_field *)p_st_node->data;
        p_pos_tmp = p_var_field->field_value.p_value;
        p_var_field->field_value.p_value = NULL;
        p_var_field->em_data_type = FRINT;
        p_var_field->field_value.i_value = atoi(p_pos_tmp);
        frfree(p_pos_tmp);

    }
    return FR_SUCC;

}


int frxml_get_float_list(const char *p_file_name,const char *p_xpath, const char *p_keyword, Frlist_header **pp_list_header)
{
    int i_ret = 0;
    int i_loop = 0;
    int i_lst_size = 0;
    Frlist_node *p_st_node = NULL;
    Frvar_field *p_var_field = NULL;
    char *p_pos_tmp = NULL;

    if(p_file_name == NULL || p_xpath == NULL || p_keyword == NULL|| pp_list_header == NULL)
        return FR_FAIL;

    i_ret = frxml_get_string_list(p_file_name, p_xpath, p_keyword, pp_list_header);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    i_lst_size = frlist_size(*pp_list_header);
    for(i_loop = 0;i_loop < i_lst_size; i_loop++)
    {
        p_st_node = frlist_node_idx(*pp_list_header, i_loop);
        p_var_field = (Frvar_field *)p_st_node->data;
        p_pos_tmp = p_var_field->field_value.p_value;
        p_var_field->field_value.p_value = NULL;
        p_var_field->em_data_type = FRFLOAT;
        p_var_field->field_value.i_value = atof(p_pos_tmp);
        frfree(p_pos_tmp);
    }

    return FR_SUCC;

}


int frxml_detect2doc_string(const char *p_file_name, const char *p_xpath, const char *p_keyword, char *p_value, int *p_i_has)
{
    xmlDocPtr p_st_doc = NULL;
    xmlXPathObjectPtr p_result = NULL;
    int i_loop = 0;
    xmlNodePtr p_st_cur = NULL;
    xmlNodeSetPtr nodeset = NULL;
    xmlChar *p_content = NULL;

    if(p_file_name == NULL || p_xpath == NULL || p_keyword == NULL)
        return FR_FAIL;

    p_st_doc = xmlReadFile(p_file_name, NULL, XML_PARSE_NOERROR|XML_PARSE_NOWARNING);
    if(p_st_doc == NULL)
    {
        FRLOG_ERROR_DETAIL("XML file parse err");
        return FR_FAIL;
    }

    //获取节点集
    p_result = __get_nodeset(p_st_doc,(xmlChar *)p_xpath);
    if(p_result)
    {
        nodeset = p_result->nodesetval;
        for (i_loop=0; i_loop < nodeset->nodeNr; i_loop++)
        {
            p_st_cur = nodeset->nodeTab[i_loop];
            p_st_cur = p_st_cur->xmlChildrenNode;
            while(p_st_cur!=NULL)
            {
                if (!xmlStrcmp(p_st_cur->name, (const xmlChar *)p_keyword))
                {
                    p_content = xmlNodeGetContent(p_st_cur);
                    if(p_content == NULL)
                    {
                        xmlXPathFreeObject (p_result);
                        xmlFreeDoc(p_st_doc);
                        return FR_FAIL;
                    }
                    if(!xmlStrcmp(p_content, (const xmlChar *)p_value))
                    {
                        *p_i_has = 1;
                        xmlFree(p_content);
                        xmlXPathFreeObject (p_result);
                        xmlFreeDoc(p_st_doc);
                        return FR_SUCC;
                    }
                    xmlFree(p_content);
                    p_content = NULL;
                }
                p_st_cur = p_st_cur->next;
            }
        }
    }

    if(p_result)
        xmlXPathFreeObject (p_result);

    xmlFreeDoc(p_st_doc);
    return FR_SUCC;

}
